package cn.tedu.lucky.draw.server.service.impl;

import cn.tedu.lucky.draw.server.common.enums.DrawEnum;
import cn.tedu.lucky.draw.server.common.enums.ErrorEnum;
import cn.tedu.lucky.draw.server.common.handler.DrawException;
import cn.tedu.lucky.draw.server.protocol.po.*;
import cn.tedu.lucky.draw.server.protocol.query.ActivityQuery;
import cn.tedu.lucky.draw.server.repository.ActivityRepository;
import cn.tedu.lucky.draw.server.repository.ActivityResultRepository;
import cn.tedu.lucky.draw.server.repository.ActivityRuleRepository;
import cn.tedu.lucky.draw.server.service.IActivityPrizeService;
import cn.tedu.lucky.draw.server.service.IActivityRuleService;
import cn.tedu.lucky.draw.server.service.IActivityService;
import cn.tedu.lucky.draw.server.service.IPrizeService;
import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;


@Service
public class ActivityServiceImpl implements IActivityService {



    List<Activity> activityList;

    @Autowired
    private ActivityRepository activityRepository;

    @Autowired
    private IActivityRuleService activityRuleService;

    @Autowired
    private ActivityResultRepository activityResultRepository;

    @Autowired
    private IPrizeService prizeService;

    @Override
    public void save(Activity activity) {
        activity.setCreateTime(LocalDateTime.now());
        activity.setUpdateTime(LocalDateTime.now());
        activity.setStatus(0);
        Activity activity1 = activityRepository.save(activity);

        activityList = null;

        if (activity1 == null)
            throw new DrawException(ErrorEnum.SYSTEM_ERROR);

    }

    @Override
    public List<Activity> findAll(ActivityQuery activityQuery) {
        if (activityList == null)
            activityList = activityRepository.findAll();

        String name = activityQuery.getName();
        Integer status = activityQuery.getStatus();

        return activityList.stream()
                .filter(activity -> (name == null || name == "" || name.equals(activity.getName())))
                .filter(activity -> (status == null || status.equals(activity.getStatus())))
                .collect(Collectors.toList());
    }

    @Override
    public List<Activity> findAll() {
        Integer status = Integer.valueOf(DrawEnum.ENABLE.getCode());
        return activityRepository.findByStatusEquals(status);
    }

    @Override
    public Activity findActivityById(Long id) {
        Optional<Activity> activityOptional = activityRepository.findById(id);
        Activity activity = null;
        if (activityOptional.isPresent()) {
            activity = activityOptional.get();
        }
        return activity;
    }

    @Override
    public Prize trigger(Long activityId) throws JSONException {
        //1.获取活动规则
        List<Rule> ruleList = activityRuleService.findRuleByActivityId(activityId);
        //2.检测用户资格
        boolean value=false;
        for (Rule rule : ruleList) {
            //如果type=1，则表示当前规则用于限制用户抽奖次数
            if (rule.getType()==1) {
                //2.1 检测抽奖次数
                JSONObject jsonObject = new JSONObject(rule.getContent());
                int count = jsonObject.getInt("count");
                Integer result = activityResultRepository
                        .countActivityResultsByActivityIdAndUserId(activityId, 99999l);
                //2.2 假如没有资格 返回结果，告知没有资格参与
                if (result >= count){
                    throw new DrawException(ErrorEnum.SYSTEM_ERROR);
                }
            }else {
                //3.检测是否降低中奖率
                JSONObject jsonObject = new JSONObject(rule.getContent());
                value = jsonObject.getBoolean("value");
            }
        }
        //获取奖品列表
        List<Prize> prizes = prizeService.findPrizesByActivityId(activityId);

        // 分配抽奖概率
        Map<Prize, Double> prizeProbabilityMap = new HashMap();
        double totalInverseValue = prizes.stream().mapToDouble(prize -> 1.0 / prize.getValue()).sum();

        // 如果需要降低概率，则所有概率值乘以一个小于1的因子
        double decreaseFactor = value ? 0.5 : 1.0;
        for (Prize prize : prizes) {
            double individualProbability = (1.0 / prize.getValue()) / totalInverseValue;
            prizeProbabilityMap.put(prize, individualProbability * decreaseFactor);
        }

        // 执行抽奖
        double randomValue = new Random().nextDouble();
        double cumulativeProbability = 0.0;
        for (Map.Entry<Prize, Double> entry : prizeProbabilityMap.entrySet()) {
            Prize prize = entry.getKey();
            Double probability = entry.getValue();
            cumulativeProbability += probability;
            //5.1 如果中奖了
            if (randomValue <= cumulativeProbability) {
                prize.setStock(prize.getStock()-1);
                prizeService.save(prize);//更新奖品库存
                saveActivityResult(activityId,prize.getId());//记录中奖信息
                return prize; // 返回中奖的奖品对象
            }
        }
        //5.2 如果没中奖
        Prize prize = new Prize();
        prize.setName("谢谢参与");
        prize.setImg("https://img.tukuppt.com/png_preview/00/44/90/VDa2b4drT2.jpg%21/fw/780");
        prize.setId(999999999L);
        //6. 记录中奖记录
        saveActivityResult(activityId,prize.getId());
        return prize;
    }

    private void saveActivityResult(Long activityId, Long prizeId) {
        ActivityResult activityResult = new ActivityResult();
        activityResult.setActivityId(activityId);
        activityResult.setUserId(99999l);//模拟用户
        activityResult.setPrizeId(prizeId);
        activityResult.setWinTime(LocalDateTime.now());
        activityResult.setStatus(0);
        activityResultRepository.save(activityResult);
    }
}
